#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>


#define chrdev_MAJOR 			200
#define chrdev_MINOR 			0
#define chrdev_DEV_CNT			1
#define chrdev_DEV_NAME 		"xby"

static char readbuf[100];
static char writebuf[100];
static char userbuf[]={"xueboyu"};

struct qudong_dev{
	dev_t devid;
	struct cdev cdev;
	struct class *class;
	struct device *device;
	int major;
	int minor;
};

struct qudong_dev newchrdev;

static int my_open(struct inode *inode, struct file *filp)  
{  
	filp->private_data = &newchrdev;
	printk("open");
    return 0;  
}  

static ssize_t my_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)  
{  
    int val=0;
	memcpy(readbuf, userbuf, sizeof(userbuf));
	val=copy_to_user(buf, readbuf, count);
    if(val==0){
		printk("userdata senddata ok!\r\n");
	}else{
		printk("userdata senddata failed!\r\n");
	}
	return 0;  
}  
  
static ssize_t my_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)  
{  
	int val=0;
	val = copy_from_user(writebuf, buf, count);
	if(val == 0){
		printk("kernel recevdata:%s\r\n", writebuf);
	}else{
		printk("kernel recevdata failed!\r\n");
	}
    return count;  
}  
  
static int my_release(struct inode *inode, struct file *filp)  
{  
    printk("close");
    return 0;  
}

static struct file_operations my_fops={
	.owner = THIS_MODULE,
	.open = my_open,
	.release = my_release,
	.write = my_write,
	.read = my_read,
};



static int __init chrdev_init (void)
{
    int ret;
    newchrdev.devid = MKDEV(chrdev_MAJOR, chrdev_MINOR);
    ret = register_chrdev_region(newchrdev.devid, chrdev_DEV_CNT, chrdev_DEV_NAME);

	newchrdev.cdev.owner = THIS_MODULE;
	cdev_init(&newchrdev.cdev,&my_fops);
	cdev_add(&newchrdev.cdev,newchrdev.devid, chrdev_DEV_CNT);
	newchrdev.class = class_create(THIS_MODULE,chrdev_DEV_NAME);
	if(IS_ERR(newchrdev.class)){
		return PTR_ERR(newchrdev.class);
	}
	newchrdev.device=device_create(newchrdev.class,NULL,newchrdev.devid,NULL,chrdev_DEV_NAME);
	if(IS_ERR(newchrdev.device)){
		return PTR_ERR(newchrdev.device);
	}
	
	return 0;
}

static void __exit chrdev_exit(void)
{
	cdev_del(&newchrdev.cdev);

    unregister_chrdev_region(newchrdev.devid, chrdev_DEV_CNT);

	device_destroy(newchrdev.class,newchrdev.devid);
	class_destroy(newchrdev.class);
}


module_init(chrdev_init);

module_exit(chrdev_exit);

MODULE_LICENSE("GPL");

MODULE_AUTHOR("xby");